Event.observeMethod()

On this page:

If this documentation is really crappy and/ or doesn't make sense, please accept my most humble apologies, I wanted to do more. However, summer is almost upon us in London, I've lost all motivation to work. It's time to get out and do out doors type stuff, not spending time writing code and documentation.

About

Event.observeMethod is based off the AOP idea I read on Encytemedia - Avoiding Bloat in Widgets a way of adding event listeners to methods in an object and running other methods BEFORE, AROUND and/ or AFTER the method you are listening to.

The code itself is small, only 49 lines (1.8kb), uncompressed.

It removes the need to create static "place holder" methods that you allow a user to over-write, with their own custom methods, and/ or creating event objects that a user can subscribe to.

It greatly simplifies the process of listening to methods in an object — only one line of code required to get you listening to an object — though there are still limitations.

It's probably not the most elegant solution, though I believe it is the quickest to use and easiest to read in your code.

Requirements

Though this can be easily backwards engineered to work without the Prototype JavaScript framework, I don't really care so to use this you will need to also be using Prototype version 1.5x, or take the time to do it yourself.

The code

How to use Event.observeMethod

Observing a method

The basics are easy, say we have two functions myFunc and myOtherFunc.

We want to run myOtherFunc after myFunc is executed.

We define our two functions:

Then we run the Event.observeMethod() function like this:

Try me!

Along with passing your method's arguments to each aspect's callbacks, if your originial method returns anything, it will not only be returned as per normal. It will also be passed in as the last argument in AFTER & AROUND aspects.

In the AROUND aspect it will only be passed in after the original method has been run (i.e. the second time the AROUND aspect's callbacks are run and not the first).

Using the aspect constants

Available for your ease/ pleasure are three constants that you can use as a fourth argument which will allow you to run your observer method, BEFORE, AROUND or AFTER (default) the method you are observing. These constants are:

  • Event.BEFORE
  • Event.AROUND
  • Event.AFTER – default

Once again, say we have two functions myNewFunc and myBeforeFunc.

We want to run myBeforeFunc after myNewFunc is executed.

We define our two functions:

Then we run the Event.observeMethod() function like this:

Try me!

Setting scope for your callback

You can use prototype's bind() function on your callback to make sure you stay within your specific scope object.

Take a look at the following code:

In it we observe two methods:

Which is called everytime a new Friend() is initialized, and:

Which is called everytime br._checkBirthdays() is run.

The first is an event observer added to a Class definition the second event observer is added to an object instansiated from a Class.

Both use the bind() function to make sure the correct scope is passed to the callback function

Stop observing a method

To stop observing a method you can use the Event.stopObservingMethod() function.

Why won't it stop observing?

Just like the normal prototype Event.stopObserving() function, you need to pass exactly the same arguments as those you did to the corresponding observeMethod call.

If you pass an anonymous function as the callback it will not be able to find it in the array of listeners!

Purging listeners

An added bonus to the whole AOP dynamic, is the ability to purge all the callbacks which are observing your method.

Depending on the amount of arguments you supply the Event.purgeListeners() function, it will behave in this way.

  1. Remove all observers from the scope object.
  2. Remove all observers from the specific method in the scope object.
  3. Remove all observers from the specific aspect (BEFORE/ AROUND/ AFTER) in the specific method in the scope object.

Limitations

Listening to a method attached to a DOM event

Once again if you have attached a method to a DOM event, Event.observeMethod() will not "hear" when the method is called unless you use Event.observeMethod() before attaching the method to the DOM event.

The easiest way around this and according to Dustin Diaz's article Seven JavaScript Techniques You Should Be Using Today "your friend when it comes to event-driven programming" is to create a bridging method.

I have included an example of this in the BirthdayReminder class:

Where the checkBirthdays() method is the bridge to the method doing all the processsing _checkBirthdays().

Methods that animate (SetTimeout/ SetInterval)

Unfortunately, Event.observeMethod() is not smart enough to run at the end of an animation so if you have a function that runs an animation, (e.g. an effect in script.aculo.us). It will run as soon as the function ends and no the Effect, which will be controlled by a setTimeout or setInterval method.

You would be better off subscribing to the animation's event callbacks, or subscribing a bridging method to the animation's event callback which you could in turn listen to.

Download

observemethod.js

No copyrights! I don't care what you do! :D